package com.eci.context.context.core;

import com.eci.common.asset.constant.StringConstant;
import com.eci.common.asset.core.Page;
import org.hibernate.property.access.internal.PropertyAccessStrategyChainedImpl;
import org.hibernate.property.access.spi.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.Temporal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class TransformSupport {
	
	private static final Logger logger = LoggerFactory.getLogger(TransformSupport.class);
	
	public static final String DB_TYPE = "2"; //1 or 2
	private static final Set<String> TRUE_STRING_SET  = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("1","Y","y"))); 
	private static final Set<String> FALSE_STRING_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("0","N","n")));
	private static final String STR_UNDERLINE = "_";
	private static final String STR_EMPTY = "";
 
	
	
	public static Object getNumberValue(Class<?> paramType,Number num) {
		 
		if (Long.class.equals(paramType) || long.class.equals(paramType)) {
		    return num.longValue();
		} else if (Integer.class.equals(paramType) || int.class.equals(paramType)) {
			return  num.intValue();
		} else if (Boolean.class.equals(paramType) || boolean.class.equals(paramType)) {
			return num.intValue() == 1;
		} else if (Float.class.equals(paramType) || float.class.equals(paramType)) {
			return num.floatValue();
		} else if (Double.class.equals(paramType) || double.class.equals(paramType)) {
			return num.doubleValue();
		} else if (Short.class.equals(paramType) || short.class.equals(paramType)) {
			return num.shortValue();
		} else if (BigDecimal.class.equals(paramType)) {
			return  num;
		} else if (String.class.equals(paramType)) {
			return num.toString();
		}
		return null;
		
	}
	
	
	public static Boolean getBooleanValue(String val) {
		 
		if(TransformSupport.TRUE_STRING_SET.contains(val)) {
			return Boolean.TRUE;
		}
		else if (TransformSupport.FALSE_STRING_SET.contains(val)) {
			return Boolean.FALSE;
		}
		
		return null;
		
	}
	
	
	public static Temporal getJava8TimeValue(Class<?> paramType,Object xtime) {
		 
		if(DB_TYPE.equalsIgnoreCase(StringConstant.Number.ONE)) {
			Timestamp timestamp = (Timestamp) xtime;
			LocalDateTime dateTime = timestamp.toLocalDateTime();
			if(LocalDateTime.class.equals(paramType)){  
				return dateTime; 
			} 
			else if(LocalDate.class.equals(paramType)){  
				return dateTime.toLocalDate();
			}
			else if(LocalTime.class.equals(paramType)){   
				return dateTime.toLocalTime();
			}
		}
		else if(DB_TYPE.equalsIgnoreCase(StringConstant.Number.TWO))  {
			if(LocalDate.class.equals(paramType)){ 
				Date sqlDate=(Date) xtime; 
				return sqlDate.toLocalDate();
			}
			else if(LocalTime.class.equals(paramType)){  
				Time sqlTime=(Time) xtime;
				return  sqlTime.toLocalTime();
			}
			else if(LocalDateTime.class.equals(paramType)){ 
				Timestamp sqlDateTime=(Timestamp) xtime;
				return sqlDateTime.toLocalDateTime(); 
			} 
		}
		
		return null;
		
	}
	
	
	/**
	 *	 根据数据库字段名在POJO查找JAVA属性名的Setter方法，参数就是数据库字段名
	 */
	@SuppressWarnings("rawtypes")
	public static Setter getSetterByColumnName(Class resultClass,Field[] allFields, String alias,
			PropertyAccessStrategyChainedImpl pasci) {
		
		// 把字段名中所有的下杠去除
		String proName = alias.replaceAll(STR_UNDERLINE, STR_EMPTY).toLowerCase();
		String lowerAlias = alias.toLowerCase();
		for (Field field : allFields) {
			// 如果不去掉下划线的字段名称和属性名对的上，或者去除下杠的字段名如果和属性名对得上，就取这个SETTER方法
			// DTO中的字段名称,变成小写
			String fieldName = field.getName().toLowerCase();
			boolean match = fieldName.equals(lowerAlias) || fieldName.equals(proName);
			if (match) {
				return pasci.buildPropertyAccess(resultClass, field.getName()).getSetter();
			}
		}
		throw new RuntimeException("Could not find DB Column[" + alias + "] Java POJO property!");
	}
	
	
	/**
	 * 	将Clob类型数据转换成字符串
	 */
	public static String clobToString(Clob clob) {
		String reString = STR_EMPTY;
		Reader is = null;
		try {
			is = clob.getCharacterStream();
			BufferedReader br = new BufferedReader(is);
			StringBuilder sb = new StringBuilder();
			String s;
			while ((s = br.readLine()) != null) {
				sb.append(s);
			}
			reString = sb.toString();
		} catch (SQLException | IOException e) {
			logger.error("Get Clob Content Failed", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					logger.error("I/O Exception", e);
				}
			}
		}
		return reString;
	}
	
	
	
	/**
	 * 	取得POJO的所有属性名(包含父类,父类的父类 .....)
	 * 
	 */
	public static Field[] getAllFields(Class<?> resultClass) {

		return getParentField(resultClass, resultClass.getDeclaredFields());

	}

	/**
	 *	递归所有父类属性
	 * 
	 * @param clazz
	 * @param fields
	 */
	private static Field[] getParentField(Class<?> clazz, Field[] fields) {

		Class<?> superClazz = clazz.getSuperclass();
		if (null == superClazz || Page.class == superClazz || Object.class == superClazz) {
			return fields;

		}
		Field[] superFields = superClazz.getDeclaredFields();

		Field[] fieldX = new Field[fields.length + superFields.length];

		System.arraycopy(fields, 0, fieldX, 0, fields.length);
		System.arraycopy(superFields, 0, fieldX, fields.length, superFields.length);

		return getParentField(superClazz, fieldX);

	}
	
	
	
}
